package com.xianyun.rpc;

import com.xianyun.rpc.config.RegistryConfig;
import com.xianyun.rpc.config.RpcConfig;
import com.xianyun.rpc.constant.RpcConstant;
import com.xianyun.rpc.registry.Registry;
import com.xianyun.rpc.registry.RegistryFactory;
import com.xianyun.rpc.utils.ConfigUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 相当于 holder，存放了全局能用到的变量，用双检查锁实现单例模式
 * @author xianYun
 * @version 1.0
 **/
@Slf4j
public class RpcApplication {
    private static volatile RpcConfig rpcConfig;

    /**
     * 提供更改默认配置类的方法。
     * @param newRpcConfig 配置类
     */
    public static void init(RpcConfig newRpcConfig){
        //读取 RPC 配置
        rpcConfig = newRpcConfig;
        log.info("rpc init, config = " + rpcConfig.toString());
        // 注册中心初始化
        RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
        Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
        registry.init(registryConfig);
        log.info("registry init, config = {}", registryConfig);
    }

    /**
     * 初始化：获取配置类对象，如果没有则用默认值初始化。
     */
    public static void init(){
        RpcConfig newRpcConfig;
        try {
            //这里有可能会抛出找不到配置文件的异常
            newRpcConfig = ConfigUtils.loadConfig(RpcConfig.class, RpcConstant.DEFAULT_CONFIG_PREFIX);
        } catch (Exception e) {
            //如果读取不到的话，则用写死的配置(默认值)。
            newRpcConfig = new RpcConfig();
        }
        init(newRpcConfig);
    }

    /**
     * 这里使用双检查锁机制保证 配置类的单例。
     * @return 配置类
     */
    public static RpcConfig getRpcConfig(){
        if(rpcConfig == null){
            synchronized (RpcApplication.class){
                if(rpcConfig == null){
                    init();
                }
            }
        }
        return rpcConfig;
    }
}
